package com.hitqz.robot.dispatch.netty.strategy.job;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.cache.Cache;
import com.hitqz.robot.api.business.dto.RobotClientSummaryDto;
import com.hitqz.robot.api.business.entity.JobCachesEntity;
import com.hitqz.robot.api.business.entity.RobotEntity;
import com.hitqz.robot.api.business.entity.RobotMapPosEntity;
import com.hitqz.robot.api.business.enums.WorkStatusEnum;
import com.hitqz.robot.biz.service.JobCachesService;
import com.hitqz.robot.biz.service.RobotMapPosService;
import com.hitqz.robot.dispatch.netty.model.DispatchJobDto;
import com.hitqz.robot.dispatch.netty.strategy.JobStrategy;
import com.hitqz.robot.dispatch.netty.util.JtsUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author xupkun
 * @date 2025/3/29
 */
@Service("doubleWheelStrategy")
@RequiredArgsConstructor
@Slf4j
public class DoubleWheelStrategy implements JobStrategy {


    private final JobCachesService jobCachesService;

    private final RobotMapPosService robotMapPosService;

    @Override
    public DispatchJobDto dispatchJob(Integer groupId) {
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");
        Cache<Integer, List<RobotEntity>> robotDispatch = SpringUtil.getBean("robotDispatch");
        // 查询当前组下的所有机器人
        List<RobotEntity> currentGroupRobot = robotDispatch.getIfPresent(groupId);
        // 检查列表是否为空
        if (currentGroupRobot == null) {
            return null;
        }
        List<JobCachesEntity> jobCachesEntityList = jobCachesService.list(Wrappers.<JobCachesEntity>lambdaQuery()
                .eq(JobCachesEntity::getGroupId, groupId)
                .orderByAsc(JobCachesEntity::getSn));
        if (CollUtil.isEmpty(jobCachesEntityList)) {
            return null;
        }
        DispatchJobDto dto = null;
        for (JobCachesEntity jobCachesEntity: jobCachesEntityList) {
            if (dto != null) {
                break;
            }
            boolean executeTask = true;
            // 相同任务不执行
            for (String clientId : posInfoDtoCache.asMap().keySet()) {
                RobotClientSummaryDto summaryDto = posInfoDtoCache.getIfPresent(clientId);
                assert summaryDto != null;
                if (StrUtil.isNotEmpty(summaryDto.getTask().getName()) &&
                        summaryDto.getTask().getName().contains(jobCachesEntity.getTaskName())
                ) {
                    executeTask = false;
                    break;
                }
            }
            if (!executeTask) {
                continue;
            }
            List<String> robotSns = currentGroupRobot.stream()
                    .filter(t -> {
                        RobotClientSummaryDto robotClientSummaryDto = posInfoDtoCache.getIfPresent(t.getRobotSn());
                        if (robotClientSummaryDto == null) {
                            return false;
                        }
                        Double battery = Double.parseDouble(robotClientSummaryDto.getStatus().getBattery());
                        if (battery <= 0.0) {
                            return false;
                        }
                        if (robotClientSummaryDto.getLogicOnlineStatus() == 0) {
                            return false;
                        }
                        return robotClientSummaryDto.getStatus().getWorkStatus() == Integer.parseInt(WorkStatusEnum.FREE.getCode());
                    })
                    .map(RobotEntity::getRobotSn)
                    .toList();
            //log.info("找到可执行的机器人:" + String.join("-", robotSns));
            if (robotSns.isEmpty()) {
                break;
            }
            // 计算距离最近的点
            // 取任务内容
            String sourceName = "";
            JSONObject jsonObject = JSONObject.parseObject(jobCachesEntity.getTaskContent());
            if (jsonObject.containsKey("fields")) {
                JSONArray jsonArray = jsonObject.getJSONArray("fields");
                for (int i = 0; i< jsonArray.size(); i++) {
                    JSONObject data = (JSONObject) jsonArray.get(i);
                    if (data.containsValue("sourcePosCode") ||   data.containsValue("sourcePosName")) {
                        sourceName = data.getString("currentValue");
                        break;
                    }
                }
            }
            RobotClientSummaryDto firstRobot = posInfoDtoCache.getIfPresent(robotSns.get(0));
            String mapCode = firstRobot.getPosition().getMapCode();

            RobotMapPosEntity robotMapPos = robotMapPosService.getOne(Wrappers.<RobotMapPosEntity>lambdaQuery()
                    .eq(RobotMapPosEntity::getName, sourceName)
                    .eq(RobotMapPosEntity::getMapCode, mapCode));
            if (robotMapPos == null) {
                robotMapPos = robotMapPosService.getOne(Wrappers.<RobotMapPosEntity>lambdaQuery()
                        .eq(RobotMapPosEntity::getCode, sourceName)
                        .eq(RobotMapPosEntity::getMapCode, mapCode));
            }
            // 查询最近的车体
            Cache<String, Polygon> robotPosPolygon = SpringUtil.getBean("robotPosPolygon");
            String bestRobot = robotSns.get(0);
            double distance = 9999;
            Point gemPoint = JtsUtil.getPoint(robotMapPos.getPosX(), robotMapPos.getPosY());
            for (String robotSn : robotSns) {
                Polygon polygon = robotPosPolygon.getIfPresent(robotSn);
                double distanceTemp = polygon.distance(gemPoint);
                log.info("robot{} 距离目标点 {}", robotSn, distanceTemp);
                if (distanceTemp < distance) {
                    bestRobot = robotSn;
                    distance = distanceTemp;
                }
            }
            // 进行任务检查 如果该任务已经是执行中任务不进行派发
            log.info("最佳执行任务{}的agv是{}", jobCachesEntity.getTaskName(), bestRobot);
            //return bestRobot;
            dto = new DispatchJobDto();
            dto.setClientId(bestRobot);
            dto.setJobId(jobCachesEntity.getId());
        }
        return dto;
    }
}
